home *** CD-ROM | disk | FTP | other *** search
/ Dr. Windows 3 / dr win3.zip / dr win3 / NEW_TECH / MENTC.ZIP / SEARCH.C < prev    next >
C/C++ Source or Header  |  1993-04-18  |  43KB  |  1,787 lines

  1. /*
  2.  * The functions in this file implement commands that search in the forward
  3.  * and backward directions.
  4.  *
  5.  * (History comments formerly here have been moved to history.c)
  6.  *
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include "estruct.h"
  11. #include "eproto.h"
  12. #include "edef.h"
  13. #include "elang.h"
  14.  
  15. /* The variables matchline and matchoff hold the line
  16.  * and offset position of the *start* of the match.
  17.  */
  18. static int    matchlen;
  19. static int    matchoff;
  20. static LINE    *matchline;
  21. static int    patlenadd;
  22. static int    lastchfjump, lastchbjump;
  23. static int    deltaf[HICHAR], deltab[HICHAR];
  24. static int    replen;        /* length of replacement string */
  25.  
  26. #if    MAGIC
  27. static int        group_count;
  28. static int    group_len[MAXGROUPS];
  29. static REGION    group_reg[MAXGROUPS];
  30. #endif
  31.  
  32. /*
  33.  * forwsearch -- Search forward.  Get a search string from the user, and
  34.  *    search for the string.  If found, reset the "." to be just after
  35.  *    the match string, and (perhaps) repaint the display.
  36.  */
  37. int PASCAL NEAR forwsearch(f, n)
  38. int f, n;    /* default flag / numeric argument */
  39. {
  40.     register int    status;
  41.  
  42.     /* If n is negative, search backwards.
  43.      * Otherwise proceed by asking for the search string.
  44.      */
  45.     if (n < 0)
  46.         return (backsearch(f, -n));
  47.  
  48.     /* Ask the user for the text of a pattern.  If the response is
  49.      * TRUE (responses other than FALSE are possible), search for
  50.      * pattern for up to n times, as long as the pattern is there
  51.      * to be found.
  52.      */
  53.     if ((status = readpattern(TEXT78, &pat[0], TRUE)) == TRUE)
  54.         status = forwhunt(f, n);
  55. /*                "Search" */
  56.  
  57.     return (status);
  58. }
  59.  
  60. /*
  61.  * forwhunt -- Search forward for a previously acquired search string.
  62.  *    If found, reset the "." to be just after the match string,
  63.  *    and (perhaps) repaint the display.
  64.  */
  65. int PASCAL NEAR forwhunt(f, n)
  66. int f, n;    /* default flag / numeric argument */
  67. {
  68.     register int    spoint = PTEND;
  69.     register int    status;
  70.  
  71.     if (n < 0)        /* search backwards */
  72.         return (backhunt(f, -n));
  73.  
  74.     /* Make sure a pattern exists, or that we didn't switch
  75.      * into MAGIC mode after we entered the pattern.
  76.      */
  77.     if (pat[0] == '\0') {
  78.         mlwrite(TEXT80);
  79. /*            "No pattern set" */
  80.         return FALSE;
  81.     }
  82.  
  83. #if    MAGIC
  84.     if ((curwp->w_bufp->b_mode & MDMAGIC) && mcpat[0].mc_type == MCNIL) {
  85.         if (!mcstr())
  86.             return FALSE;
  87.     }
  88. #endif
  89.  
  90.     /*
  91.      * Do one extra search to get us past our current
  92.      * match, if the search type has us at the start
  93.      * of a match, instead of after a match.
  94.      */
  95.     if (searchtype == SRBEGIN) {
  96.         spoint = PTBEG;
  97.         if (lastflag & CFSRCH)
  98.             n = (n > 2)? (n + 1): 2;
  99.     }
  100.  
  101. #if    MAGIC
  102.     if (magical && (curwp->w_bufp->b_mode & MDMAGIC))
  103.         status = mcscanner(FORWARD, spoint, n);
  104.     else
  105. #endif
  106.         status = scanner(FORWARD, spoint, n);
  107.  
  108.     /* Complain if not there.
  109.      */
  110.     if (status == FALSE)
  111.         mlwrite(TEXT79);
  112. /*            "Not found" */
  113.  
  114.     thisflag |= CFSRCH;
  115.     return (status);
  116. }
  117.  
  118. /*
  119.  * backsearch -- Reverse search.  Get a search string from the user, and
  120.  *    search, starting at "." and proceeding toward the front of the buffer.
  121.  *    If found "." is left pointing at the first character of the pattern
  122.  *    (the last character that was matched).
  123.  */
  124. int PASCAL NEAR backsearch(f, n)
  125. int f, n;    /* default flag / numeric argument */
  126. {
  127.     register int    status;
  128.  
  129.     /* If n is negative, search forwards.
  130.      * Otherwise proceed by asking for the search string.
  131.      */
  132.     if (n < 0)
  133.         return (forwsearch(f, -n));
  134.  
  135.     /* Ask the user for the text of a pattern.  If the response is
  136.      * TRUE (responses other than FALSE are possible), search for
  137.      * pattern for up to n times, as long as the pattern is there
  138.      * to be found.
  139.      */
  140.     if ((status = readpattern(TEXT81, &pat[0], TRUE)) == TRUE)
  141.         status = backhunt(f, n);
  142. /*                "Reverse search" */
  143.  
  144.     return (status);
  145. }
  146.  
  147. /*
  148.  * backhunt -- Reverse search for a previously acquired search string,
  149.  *    starting at "." and proceeding toward the front of the buffer.
  150.  *    If found "." is left pointing at the first character of the pattern
  151.  *    (the last character that was matched).
  152.  */
  153. int PASCAL NEAR backhunt(f, n)
  154. int f, n;    /* default flag / numeric argument */
  155. {
  156.     register int    spoint = PTBEG;
  157.     register int    status;
  158.  
  159.     if (n < 0)
  160.         return (forwhunt(f, -n));
  161.  
  162.     /* Make sure a pattern exists, or that we didn't switch
  163.      * into MAGIC mode after we entered the pattern.
  164.      */
  165.     if (tap[0] == '\0') {
  166.         mlwrite(TEXT80);
  167. /*            "No pattern set" */
  168.         return FALSE;
  169.     }
  170. #if    MAGIC
  171.     if ((curwp->w_bufp->b_mode & MDMAGIC) && tapcm[0].mc_type == MCNIL) {
  172.         if (!mcstr())
  173.             return FALSE;
  174.     }
  175. #endif
  176.  
  177.     /*
  178.      * Do one extra search to get us past our current
  179.      * match, if the search type has us at the start
  180.      * of a match, instead of after a match.
  181.      */
  182.     if (searchtype == SREND) {
  183.         spoint = PTEND;
  184.         if (lastflag & CFSRCH)
  185.             n = (n > 2)? (n + 1): 2;
  186.     }
  187.  
  188. #if    MAGIC
  189.     if (magical && (curwp->w_bufp->b_mode & MDMAGIC))
  190.         status = mcscanner(REVERSE, spoint, n);
  191.     else
  192. #endif
  193.         status = scanner(REVERSE, spoint, n);
  194.  
  195.     /* Complain if not there.
  196.      */
  197.     if (status == FALSE)
  198.         mlwrite(TEXT79);
  199. /*            "Not found" */
  200.  
  201.     thisflag |= CFSRCH;
  202.     return (status);
  203. }
  204.  
  205. #if    MAGIC
  206. /*
  207.  * mcscanner -- Search for a meta-pattern in either direction.  If found,
  208.  *    reset the "." to be at the start or just after the match string,
  209.  *    and (perhaps) repaint the display.
  210.  */
  211. int PASCAL NEAR mcscanner(direct, beg_or_end, repeats)
  212. int    direct;        /* which way to go.*/
  213. int    beg_or_end;    /* put point at beginning or end of pattern.*/
  214. int    repeats;    /* search repetitions.*/
  215. {
  216.     MC    *mcpatrn;    /* pointer into pattern */
  217.     LINE    *curline;    /* current line during scan */
  218.     int    curoff;        /* position within current line */
  219.  
  220.     /* If we are going in reverse, then the 'end' is actually
  221.      * the beginning of the pattern.  Toggle it.
  222.      */
  223.     beg_or_end ^= direct;
  224.  
  225.     /* Another directional problem: if we are searching forwards,
  226.      * use the pattern in mcpat[].  Otherwise, use the reversed
  227.      * pattern in tapcm[].
  228.      */
  229.     mcpatrn = (direct == FORWARD)? &mcpat[0]: &tapcm[0];
  230.  
  231.     /* Setup local scan pointers to global ".".
  232.      */
  233.     curline = curwp->w_dotp;
  234.     curoff  = curwp->w_doto;
  235.  
  236.     /* Scan each character until we hit the head link record.
  237.      */
  238.     while (!boundry(curline, curoff, direct)) {
  239.         /* Save the current position in case we need to
  240.          * restore it on a match, and initialize matchlen to
  241.          * zero in case we are doing a search for replacement.
  242.          */
  243.         matchline = curline;
  244.         matchoff = curoff;
  245.         matchlen = 0;
  246.  
  247.         if (amatch(mcpatrn, direct, &curline, &curoff)) {
  248.             /* A SUCCESSFULL MATCH!!!
  249.              * Flag that we have moved,
  250.              * reset the global "." pointers.
  251.              */
  252.             curwp->w_flag |= WFMOVE;
  253.             if (beg_or_end == PTEND)    /* at end of string */
  254.             {
  255.                 curwp->w_dotp = curline;
  256.                 curwp->w_doto = curoff;
  257.             }
  258.             else        /* at beginning of string */
  259.             {
  260.                 curwp->w_dotp = matchline;
  261.                 curwp->w_doto = matchoff;
  262.             }
  263.  
  264.             /* If we're heading in reverse, set the "match"
  265.              * pointers to the start of the string, for savematch().
  266.              */
  267.             if (direct == REVERSE) {
  268.                 matchline = curline;
  269.                 matchoff = curoff;
  270.             }
  271.  
  272.             if (savematch() == ABORT)
  273.                 return ABORT;
  274.  
  275.             /* Continue scanning if we haven't found
  276.              * the nth match.
  277.              */
  278.             if (--repeats <= 0)
  279.                 return TRUE;
  280.         }
  281.  
  282.         /* Advance the cursor.
  283.          */
  284.         nextch(&curline, &curoff, direct);
  285.     }
  286.  
  287.     return FALSE;    /* We could not find a match.*/
  288. }
  289.  
  290. /*
  291.  * amatch -- Search for a meta-pattern in either direction.  Based on the
  292.  *    recursive routine amatch() (for "anchored match") in
  293.  *    Kernighan & Plauger's "Software Tools".
  294.  */
  295. int PASCAL NEAR    amatch(mcptr, direct, pcwline, pcwoff)
  296. register MC    *mcptr;        /* pattern to scan for */
  297. int        direct;        /* which way to go.*/
  298. LINE        **pcwline;    /* current line during scan */
  299. int        *pcwoff;    /* position within current line */
  300. {
  301.     register int    c;    /* character at current position */
  302.     LINE    *curline;    /* current line during scan */
  303.     int    curoff;        /* position within current line */
  304.     int    n_chars;    /* number of chars matched in a closure.*/
  305.     int    cl_min;        /* minimum number of chars matched in closure.*/
  306.     int    cl_type;    /* Which closure type?.*/
  307.  
  308.     /* Set up lo